#include "stdio.h"
#include "ff.h"
#include "string.h"
#include "stm32g4xx_hal.h"

// 音频参数（需与后续电脑转换时一致）
#define AUDIO_SAMPLE_RATE 44100
#define AUDIO_CHANNELS    2
#define AUDIO_BIT_DEPTH   16
#define RECORD_DURATION   2   // 录制2秒
#define BUFFER_SIZE       512 // 缓冲区大小（字节），已验证可行

// 计算总数据量（字节）：采样率×时长×声道数×(位深/8)
#define TOTAL_BYTES (AUDIO_SAMPLE_RATE * RECORD_DURATION * AUDIO_CHANNELS * (AUDIO_BIT_DEPTH / 8))

// 全局缓冲区（避免栈溢出）
uint8_t audio_buffer1[BUFFER_SIZE];

// FATFS错误描述
const char* get_fatfs_error_desc(FRESULT res) {
    static const char* desc[] = {
        "Success", "Disk I/O error", "Internal error", "Drive not ready",
        "File not found", "Path not found", "Invalid filename", "Access denied",
        "File exists", "Invalid object", "Write protected", "Invalid drive",
        "Drive not enabled", "No filesystem", "MKFS aborted", "Timeout",
        "File locked", "Not enough core", "Too many files"
    };
    return (res >= 0 && res < sizeof(desc)/sizeof(desc[0])) ? desc[res] : "Unknown error";
}

// 生成模拟PCM数据（16位双声道）
void generate_pcm_data(uint8_t *buffer, uint32_t size) {
    static uint16_t sample = 0; // 16位样本值
    uint16_t *buf_16 = (uint16_t*)buffer;
    uint32_t samples_count = size / 2; // 每个样本2字节
    
    for (uint32_t i = 0; i < samples_count; i++) {
        // 生成正弦波样本（范围：-32767~32767）
        int16_t sin_sample = (int16_t)(32767 * sin(2 * 3.1415926 * 440 * sample / AUDIO_SAMPLE_RATE));
        
        // 双声道数据（左右声道相同）
        buf_16[i * 2] = sin_sample;       // 左声道
        buf_16[i * 2 + 1] = sin_sample;   // 右声道
        
        sample++;
        if (sample >= AUDIO_SAMPLE_RATE) sample = 0; // 循环生成
    }
}

// 录制PCM数据到bin文件
HAL_StatusTypeDef record_pcm_to_bin(const char* filename) {
    FIL file;
    FRESULT res;
    UINT bytes_written;
    uint32_t total_written = 0;
    uint32_t attempts = 0;
    
    // 创建文件（二进制写入模式）
    res = f_open(&file, filename, FA_CREATE_ALWAYS | FA_WRITE);
    if (res != FR_OK) {
        printf("Failed to create file: %s\n", get_fatfs_error_desc(res));
        return HAL_ERROR;
    }
    printf("Recording to %s (Target: %u bytes)\n", filename, TOTAL_BYTES);
    
    // 循环录制
    while (total_written < TOTAL_BYTES) {
        // 计算本次写入大小
        uint32_t remaining = TOTAL_BYTES - total_written;
        uint32_t write_size = (remaining < BUFFER_SIZE) ? remaining : BUFFER_SIZE;
        
        // 生成PCM数据
        generate_pcm_data(audio_buffer1, write_size);
        
        // 写入数据（带重试）
        uint8_t retry = 3;
        while (retry-- > 0) {
            res = f_write(&file, audio_buffer1, write_size, &bytes_written);
            if (res == FR_OK && bytes_written == write_size) break;
            HAL_Delay(5); // 重试前延迟
        }
        
        // 检查写入结果
        if (res != FR_OK || bytes_written != write_size) {
            printf("Write failed at %u bytes (attempt %u)\n", total_written, attempts);
            printf("Error: %s (Wrote %u/%u)\n", get_fatfs_error_desc(res), bytes_written, write_size);
            f_close(&file);
            return HAL_ERROR;
        }
        
        total_written += bytes_written;
        attempts++;
        
        // 打印进度（每10%）
        if (total_written % (TOTAL_BYTES / 10) == 0) {
            printf("Progress: %.0f%% (%u/%u bytes)\n",
                  (float)total_written / TOTAL_BYTES * 100, total_written, TOTAL_BYTES);
        }
        
        // 小缓冲区延迟，避免高频写入压力
        HAL_Delay(1);
    }
    
    // 强制同步并关闭文件
    f_sync(&file);
    f_close(&file);
    
    printf("Recording completed: %u bytes in %u attempts\n", total_written, attempts);
    return HAL_OK;
}

// 主测试函数
void pcm_bin_test(void) {
    FRESULT res;
    FATFS fs;
    char filename[32];
    static uint8_t file_num = 1;
    
    // 生成文件名（如pcm_rec_1.bin）
    sprintf(filename, "pcm_rec_%d.bin", file_num++);
    
    printf("\n===== Starting PCM bin recording test =====\n");
    printf("Audio parameters: %uHz, %u channels, %u bits, %u seconds\n",
           AUDIO_SAMPLE_RATE, AUDIO_CHANNELS, AUDIO_BIT_DEPTH, RECORD_DURATION);
    
    // 挂载文件系统
    res = f_mount(&fs, "", 1);
    if (res != FR_OK) {
        printf("Filesystem mount failed: %s\n", get_fatfs_error_desc(res));
        return;
    }
    
    // 执行录制
    if (record_pcm_to_bin(filename) == HAL_OK) {
        printf("Successfully created %s\n", filename);
        printf("To convert to WAV: Use Audacity or ffmpeg with same parameters\n");
    } else {
        printf("Recording failed\n");
    }
    
    // 卸载文件系统
    f_mount(NULL, "", 1);
    printf("===== Test finished =====\n");
}
